package com.example.othree.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.othree.common.AdminUserDetails;
import com.example.othree.common.CommonMessage;
import com.example.othree.common.R;
import com.example.othree.entity.User;
import com.example.othree.mapper.DroneManagementMapper;
import com.example.othree.mapper.UserMapper;
import com.example.othree.service.UserService;
import com.example.othree.util.JwtTokenUtil;
import com.example.othree.util.RedisUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.security.core.AuthenticationException;

import javax.annotation.Resource;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Resource
    DroneManagementMapper droneManagementMapper;

    @Override
    public User getUserByEmail(String email) {
        return userMapper.getUserByEmail(email);
    }

    @Override
    public UserDetails loadUserByEmail(String email){
        //获取用户信息
        User user = getUserByEmail(email);
        if (user != null) {
            return new AdminUserDetails(user);
        }
        throw new UsernameNotFoundException("邮箱或密码错误");
    }

    @Override
    public String login(String email, String password) {
        String token = null;

        // 1. 查询用户
        User user = this.lambdaQuery()
                .eq(User::getEmail, email)
                .eq(User::getIsRoot, 0)
                .one();

        // 2. 检查用户是否存在
        if (user == null) {
            LOGGER.warn("登录失败: 邮箱 {} 不存在", email);
            return null;
        }

        try {
            // 3. 验证密码 - 这是关键修改！
            if (!bCryptPasswordEncoder.matches(password, user.getPassword())) {
                LOGGER.warn("登录失败: 邮箱 {} 密码错误", email);
                return null; // 密码错误直接返回null
            }

            // 4. 密码正确，继续执行后面的逻辑
            UserDetails userDetails = loadUserByEmail(email);

            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);

            token = jwtTokenUtil.generateToken(userDetails, CommonMessage.Client.ADMIN.client);

            // 缓存登录token
            if (token != null) {
                // 建议存储更有意义的数据，比如用户信息
                redisUtils.set(email, token);
                redisUtils.set(token, user.getUsername()); // 存储用户名而不是token本身

                // 最好设置过期时间，与JWT过期时间一致
                // redisUtils.expire(email, 3600, TimeUnit.SECONDS);
                // redisUtils.expire(token, 3600, TimeUnit.SECONDS);
            }

        } catch (AuthenticationException e) {
            LOGGER.warn("登录异常:{}", e.getMessage());
        }

        return token;
    }

    @Override
    public String refreshToken(String oldToken, String email) {
        String token = jwtTokenUtil.refreshHeadToken(oldToken);
        // 缓存登录token
        redisUtils.setCacheObject(email, token);
        return token;
    }

    @Override
    public IPage PageList(IPage<User> page, Wrapper wrapper) { return userMapper.PageList(page,wrapper);}


}
